package top.wkl.springboot3.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import top.wkl.springboot3.base.R;
import top.wkl.springboot3.entity.user.AuthInfo;
import top.wkl.springboot3.entity.user.TbAction;
import top.wkl.springboot3.entity.user.TbRoleAction;
import top.wkl.springboot3.entity.user.TbUser;
import top.wkl.springboot3.interceptor.AppInterceptor;
import top.wkl.springboot3.mapper.user.TbActionMapper;
import top.wkl.springboot3.mapper.user.TbRoleActionMapper;
import top.wkl.springboot3.mapper.user.TbUserMapper;
import top.wkl.springboot3.service.AuthService;
import top.wkl.springboot3.service.RedisService;
import top.wkl.springboot3.util.EncryptorUtils;
import top.wkl.springboot3.vo.AuthUser;
import top.wkl.springboot3.vo.UserPwd;

import java.util.UUID;

@Service
@Slf4j
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {
    private final TbUserMapper tbUserMapper;
    private final RedisService redisService;
    private final TbRoleActionMapper tbRoleActionMapper;
    private final TbActionMapper tbActionMapper;
    public static final int ROLE_ADMIN = 1;
    public static final int ROLE_USER = 2;

    @Override
    public R<String> changePwd(UserPwd pwd) {
        //获取认证信息
        AuthInfo authInfo = AppInterceptor.getAuthInfo();
        String token = authInfo.getToken();
        Integer id = redisService.get(token, Integer.class);
        TbUser user = tbUserMapper.selectById(id);
        String oldpwd = EncryptorUtils.saltMd5(pwd.getOldpwd(), user.getSalt());
        if (!oldpwd.equals(user.getPassword())) {
            return R.fail("原密码不正确");
        }
        //修改密码
        String newpwd = EncryptorUtils.saltMd5(pwd.getNewpwd(), user.getSalt());
        user.setPassword(newpwd);
        tbUserMapper.updateById(user);
        return R.ok("修改密码成功");
    }

    @Override
    public R<String> reg(AuthUser user) {
        TbUser add = new TbUser();
        TbUser check = queryByName(user.getUsername());
        if (check != null) {
            return R.fail("用户名已存在");
        }
        add.setUsername(user.getUsername());
        String salt = EncryptorUtils.randString(6);
        add.setSalt(salt);
        add.setPassword(EncryptorUtils.saltMd5(user.getPassword(), salt));
        add.setRole(ROLE_USER);
        tbUserMapper.insert(add);
        return R.ok("注册成功");
    }

    @Override
    public boolean auth() {
        //获取认证信息
        AuthInfo authInfo = AppInterceptor.getAuthInfo();
        log.debug("认证信息：{}", authInfo);
        //判断请求的方法是否被托管
        QueryWrapper<TbAction> aqw = new QueryWrapper<>();
        aqw.eq("mapping", authInfo.getMapping());
        aqw.eq("method", authInfo.getMethod());
        TbAction action = tbActionMapper.selectOne(aqw);
        log.debug("托管信息：{}", action);
        if (action == null) {
            //没有被托管的就直接通过校验
            return true;
        }
        //验证token和用户id信息
        String token = authInfo.getToken();
        if (!StringUtils.hasText(token) || !redisService.has(token)) {
            return false;
        }
        Integer id = redisService.get(token, Integer.class);
        if (id == null) {
            return false;
        }
        //获取用户信息
        TbUser user = tbUserMapper.selectById(id);
        log.debug("用户信息：{}", user);
        if (user == null) {
            return false;
        }
        //校验授权信息
        QueryWrapper<TbRoleAction> rqw = new QueryWrapper<>();
        rqw.eq("role", user.getRole());
        rqw.eq("action", action.getId());
        TbRoleAction roleAction = tbRoleActionMapper.selectOne(rqw);
        log.debug("授权信息：{}", roleAction);
        return roleAction != null;
    }

    @Override
    public TbUser queryByName(String name) {
        QueryWrapper<TbUser> Wrapper = new QueryWrapper<>();
        Wrapper.eq("username", name);
        return tbUserMapper.selectOne(Wrapper);
    }

    @Override
    public R<TbUser> login(AuthUser user) {
        //查询用户是否存在
        TbUser check = queryByName(user.getUsername());
        if (check == null) {
            return R.fail("用户不存在", null);
        }
        //加密密码判定
        String pwd = EncryptorUtils.saltMd5(user.getPassword(), check.getSalt());
        if (!check.getPassword().equals(pwd)) {
            return R.fail("密码错误", null);
        }
        R<TbUser> r = R.ok("登录成功", check);
        //token信息处理
        String token = UUID.randomUUID().toString();
        redisService.save(token, check.getId(), 3 * 24 * 60 * 60);
        r.setToken(token);
        return r;

    }

    @Override
    public R<TbUser> getLoginUser() {
        //获取认证信息
        AuthInfo authInfo = AppInterceptor.getAuthInfo();
        if (authInfo.getId() == null) {
            return R.fail("用户未登录", null);
        }
        TbUser user = tbUserMapper.selectById(authInfo.getId());
        if (user == null) {
            return R.fail("用户不存在", null);
        }
        return R.ok("", user);
    }

    @Override
    public R<String> logout() {
        AuthInfo authInfo = AppInterceptor.getAuthInfo();
        String token = authInfo.getToken();
        token = token == null ? "" : token;
        if (redisService.has(token)) {
            redisService.remove(token);
        }
        return R.ok("退出成功");
    }


}

